package cn.wb.base.service.impl;

import cn.wb.base.cons.PhoneRegisterCon;
import cn.wb.base.dto.PhoneRegisterDto;
import cn.wb.base.dto.SmsCodeDto;
import cn.wb.base.service.VerifyCodeService;
import cn.wb.base.util.BusinessException;
import cn.wb.base.util.VerifyCodeUtils;
import cn.wb.user.domain.Logininfo;
import cn.wb.user.domain.User;
import cn.wb.user.mapper.LogininfoMapper;
import cn.wb.user.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class VerifyCodeServiceImpl implements VerifyCodeService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private LogininfoMapper logininfoMapper;

    /**
     * 获取图形验证码
     *
     * @param imageCodeKey
     * @return
     */
    @Override
    public String imageCode(String imageCodeKey) throws IOException {
        // 参数校验
        // 生成图形验证码
        String imageCode = VerifyCodeUtils.generateVerifyCode(1);
        // 存到redis
        redisTemplate.opsForValue().set(imageCodeKey, imageCode, 3, TimeUnit.MINUTES);
        // 返回图形验证码
        return VerifyCodeUtils.VerifyCode(80, 30, imageCode);
    }


    /**
     * 发送手机验证码
     *
     * @param dto
     */
    @Override
    public void smsCode(SmsCodeDto dto) {
        if ("binder".equals(dto.getType())){
            // 发送短信
            this.sendSms(PhoneRegisterCon.BINDER_REDIS_KEY,dto);
        }else if ("register".equals(dto.getType())){
            // 图形验证码验证
            this.imageVerify(dto);
            // 发送短信
            this.sendSms(PhoneRegisterCon.REDIS_KEY,dto);
        }
    }

    /**
     * 手机号注册
     * @param dto
     */

    @Override
    public void phoneRegister(PhoneRegisterDto dto) {
        // 校验参数
        // 校验手机验证码，是否过期，是否正确
        String redisSmsCode = (String) redisTemplate.opsForValue().get(String.format(PhoneRegisterCon.REDIS_KEY
                , dto.getPhone()));
        if (StringUtils.isBlank(redisSmsCode) || !dto.getSmsCode().equals(redisSmsCode)){
            throw new BusinessException("验证码有误！");
        }
        // 判断两次密码是否一致
        if (!dto.getPassword().equals(dto.getPasswordRepeat())){
            throw new BusinessException("两次密码不一致！");
        }
        // 手机号注册过？
        User user = userMapper.findByPhone(dto.getPhone());
        if (null != user) {
            throw new BusinessException("滚去登录！");
        }
        // 保存数据，user 和 logininfo
         // 转换user对象
        user = dto.getUser();
         // 转换logininfo对象
        Logininfo logininfo = new Logininfo();
        BeanUtils.copyProperties(user,logininfo);
        logininfo.setType(1);
        logininfo.setDisable(1);
        // 先去添加logininfo对象
        logininfoMapper.add(logininfo);
        // 再去添加user对象
        user.setLogininfoId(logininfo.getId());
        userMapper.add(user);
    }

    private void sendSms(String redisKey,SmsCodeDto dto) {
        // 4.两次发送时间是否大于60秒
        // 获取手机验证码是否在60秒内
        Long expire = redisTemplate.getExpire(String.format(redisKey
                , dto.getPhone()));
        if (null != expire && expire > (PhoneRegisterCon.REDIS_TTL - 1) * 60L) {
            throw new BusinessException("60内别发了！");
        }
        // 5.是否需要重置验证码
        // 如果redis中不存在验证码 1.第一次来  2.过期了
        String smsCode = (String) redisTemplate.opsForValue().get(String.format(redisKey
                , dto.getPhone()));
        if (StringUtils.isBlank(smsCode)) {
            smsCode = VerifyCodeUtils.generateVerifyCode(4);
        }
        log.info("手机验证码为:{}",smsCode);
        // 6.将手机验证码存到redis中
        redisTemplate.opsForValue().set(String.format(redisKey
                        , dto.getPhone()), smsCode, PhoneRegisterCon.REDIS_TTL
                , TimeUnit.MINUTES);
        // 7.发送短信
//        SendSmsUtil.send(dto.getPhone(),smsCode);
    }

    private void imageVerify(SmsCodeDto dto) {
        // 1.参数校验
        // 2.判断图形验证码,是否存在,是否正确
        // 通过uuid取出来图形验证码 对比传入的图形验证码
        String redisImageCode = (String) redisTemplate.opsForValue().get(dto.getImageCodeKey());
        if (StringUtils.isBlank(redisImageCode) || !dto.getImageCodeValue().equalsIgnoreCase(redisImageCode)) {
            throw new BusinessException("图形验证码错误！");
        }
        // 3.判断手机号是否注册过
        // 根据手机号去查询用户数据
        User user = userMapper.findByPhone(dto.getPhone());
        if (null != user) {
            throw new BusinessException("滚去登录！");
        }
        // 删除图形验证码
        redisTemplate.delete(dto.getImageCodeKey());
    }
}
